
// <OBJECT id=MSComm1 CLASSID="clsid:648A5600-2C6E-101B-82B6-000000000014"
// codebase="MSCOMM32.OCX" type="application/x-oleobject">
//     </OBJECT>
//
//     <SCRIPT   ID=clientEventHandlersJS   LANGUAGE=javascript>
//     function   MSComm1_OnComm()
//     {
//         ComPortGlobal.msComm_event();
//     }
//     </SCRIPT>
//
//     <SCRIPT  LANGUAGE=javascript   FOR=MSComm1   EVENT=OnComm>
//     // MSComm1控件每遇到 OnComm 事件就调用 MSComm1_OnComm()函数
//     MSComm1_OnComm()
//     </SCRIPT>

//加载MSComm控件声明和事件触发Html代码
document.write("<OBJECT id=MSComm1 CLASSID=\"clsid:648A5600-2C6E-101B-82B6-000000000014\"\n" +
    "        codebase=\"MSCOMM32.OCX\" type=\"application/x-oleobject\">\n" +
    "</OBJECT>\n" +
    "\n" +
    "<SCRIPT   ID=clientEventHandlersJS   LANGUAGE=javascript>\n" +
    "    function   MSComm1_OnComm()\n" +
    "    {\n" +
    "        ComPortGlobal.msComm_event();\n" +
    "    }\n" +
    "</SCRIPT>\n" +
    "\n" +
    "<SCRIPT  LANGUAGE=javascript   FOR=MSComm1   EVENT=OnComm>\n" +
    "    MSComm1_OnComm()\n" +
    "</SCRIPT>");

/**
 * 串口封装对象
 */
function ComPort() {
    this.com = undefined;
    // this.activeXName = undefined;
    this.isInit = false;    //是否已初始化控件
    this.isOpen = false;    //串口是否被打开
    this.baudRate = "9600"; //波特率
    this.dataBits = "8";  //数据位
    this.verifyBits = "N"; //校检位 None
    this.stopBits = "1"; //停止位
    //this.form = "utf-8"; //格式
    this.comNum = "1"; //Com名称编号 如Com1则为"1"
    // this.queryDataIntervalTime = 100;   //发送查询指令时的循环读取接收数据的时间毫秒数
    this.dataCallback = undefined;
    this.isSingleDataCallback = false;    //是否单次数据回调，如果为true，则保证每次串口数据回调触发时只调用一次回调
    // this._isReadData = false;
    window.ComPortGlobal = this;
}

/**
 * Com控件发送接收事件
 */
ComPort.prototype.msComm_event = function(){
    // console.log("this.com.CommEvent:"+this.com.CommEvent);
    if(this.com.CommEvent === 2){   //触发接收事件
        var data = this.com.Input;
        // console.log("串口接收数据："+data);
        this.handleData(data);
    }
}

/**
 * 处理响应数据
 */
ComPort.prototype.handleData = function(data){
    if(this.dataCallback !== undefined){    //如果数据回调存在则调用数据回调
        //如果采用是单次数据回调，则先将回调引用设置为null，再调用回调
        if(this.isSingleDataCallback){
            var lastCallback = this.dataCallback;
            this.dataCallback = undefined;
            lastCallback(data);
        }
        //如果没有采用单次数据回调，则直接调用回调，不清空回调引用
        else{
            this.dataCallback(data);
        }
    }
}

/**
 * 配置串口参数
 */
ComPort.prototype.configCommParam = function(){
    //串行端口号
    this.com.CommPort = this.comNum;
    this.com.DataBits = this.dataBits;
    this.com.StopBits = this.stopBits;
    this.com.BaudRate = this.baudRate;
    //"9600,N,8,1" 9600：波特率 n：奇偶位 8：数据位 1：停止位
    this.com.Settings = this.baudRate + ","+this.verifyBits+","+this.dataBits+","+this.stopBits;
    //其它参数
    this.com.RTSEnable = 1;
    this.com.DTREnable = 1;
    this.com.Handshaking = 1;
    this.com.ParityReplace = "?";
    this.com.EOFEnable = 0;
    this.com.InputMode = 0;
    this.com.InBufferSize = 1024;
    this.com.InputLen = 0;
    this.com.OutBufferSize = 512;
    this.com.SThreshold = 0;
    // this.com.SThreshold = 17;
    this.com.RThreshold = 1;
}
/**
 * 打开串口
 */
ComPort.prototype.open = function(){
    if(!this.isInit){
        if(this.initActiveX("MSComm1") === false){
            return false;
        }
        // console.error("串口控件未被初始化！");
        // return false;
    }
    if(this.com.PortOpen === false){    //如果串口为关闭则打开串口
        try{
            //配置串口参数
            this.configCommParam();
            //打开串口
            this.com.PortOpen = true;
            //绑定收发事件
            // this.bindComPortEvent();
        }catch (e) {
            console.error("串口打开错误！"+e);
            return false;
        }
        this.isOpen = true;
        console.log("串口打开成功！");
        return true;
    }else if(this.com.PortOpen === true){
        console.warn("串口已经被打开！");
        return false;
    }
}

/**
 * 使用指定串口ActiveX控件名称初始化控件对象
 * @param activeXName   //控件名称(Object标签ID)
 */
ComPort.prototype.initActiveX = function(activeXName){
    if(this.isInit){
        console.warn("串口控件已被初始化！");
        return false;
    }
    if(activeXName === undefined){
        console.error("请传入activeX控件名称！");
        return false;
    }
    try{
        this.com = document.getElementById(activeXName);
        if(this.com.PortOpen === undefined){    //如果PortOpen属性存在则控件初始化成功
            console.error("串口控件初始化失败，请安装串口插件！");
        }else{
            console.log("串口控件初始化成功");
            this.isInit = true;
            // this.activeXName = activeXName;
            return true;
        }
    }catch (e) {
        console.error("串口控件初始化错误! "+e);
    }
    return false;
}


/**
 * 发送数据
 */
ComPort.prototype.sendData = function (data,callback) {
    // if(this._isReadData){
    //     console.error("上一次串口操作还未完成");
    // }
    if(this.com.PortOpen === false){
        console.error("发送数据出错！串口还未打开！");
        return;
    }
    console.log("send data:"+data);
    try{
        //先清空发送和接收缓冲区
        this.com.OutBufferCount = 0;
        this.com.InBufferCount = 0;
        //设置数据回调
        // if(this.dataCallback !== undefined){
            // this._isReadData = true;
            this.dataCallback = callback;
        // }
        //发送数据
        this.com.Output = data;
    }catch (e) {
        console.error("发送数据出错！"+e);
        return;
    }
    // if(callback === undefined){ //如果回调为空则不进行接收数据
    //     return;
    // }
    // //接收数据
    // try{
    //     //循环读取数据
    //     // var cont = timeOutMsec / this.queryDataIntervalTime;
    //     // var responseData = undefined;
    //     var temp_this = this;
    //     temp_this._isReadData = true;
    //     var interval = setInterval(function () {
    //         if(temp_this.com.CommEvent === 2){
    //             var responseData = temp_this.com.Input;
    //             callback(responseData);
    //             temp_this._isReadData = false;
    //             clearInterval(interval);
    //         }
    //     },this.queryDataIntervalTime);
    //     alert("aaa");
    //     setTimeout(function () {
    //         temp_this._isReadData = false;
    //         alert("ccc");
    //         clearInterval(interval);
    //     },timeOutMsec);
    //     alert("bbb");
    //
    //     //
    //     //
    //     // for(var i = 0;i < cont;i++){
    //     //     if(this.com.InBufferCount != 0){
    //     //         this.com.Input
    //     //     }
    //     //     setTimeout("responseData = ;",this.queryDataIntervalTime);
    //     // }
    // }catch (e) {
    //     console.error("接收数据出错！"+e);
    // }
}

// ComPort.prototype.checkInput = function(){
//     if(this.com.CommEvent === 2){
//         return this.com.Input;
//     }
// }

// /**
//  * 发送会收到结果的数据
// * @param data 发送的数据
// * @param timeOutMsec 接收数据超时时间毫秒数
// */
// ComPort.prototype.query = function (data,refunction,timeOutMsec){
//     if(timeOutMsec <= this.queryDataIntervalTime){
//         console.error("查询方法超时时间不能小于等于"+this.queryDataIntervalTime);
//     }
//     console.log("query data:"+data);
//     try{
//         //先清空发送和接收缓冲区
//         this.com.OutBufferCount = 0;
//         this.com.InBufferCount = 0;
//         //发送数据
//         this.com.Output = data;
//
//         //循环读取数据
//         var cont = timeOutMsec / this.queryDataIntervalTime;
//         var responseData = "";
//         for(var i = 0;i < cont;i++){
//             setTimeout("",this.queryDataIntervalTime);
//         }
//
//     }catch (e) {
//         console.error("查询数据出错！"+e);
//     }
// }

/**
 * 关闭串口
*/
ComPort.prototype.close = function () {
    if(this.com.PortOpen === undefined){
        this.isOpen = false;
        console.warn("串口关闭失败，串口还未被初始化！");
        return false;
    }
    if(this.com.PortOpen === true){    //如果串口为打开则关闭串口
        try{
            this.com.PortOpen = false;
        }catch (e) {
            console.log("串口关闭错误！"+e);
            return false;
        }
        this.isOpen = false;
        console.log("串口关闭成功！");
        return true;
    }else{
        this.isOpen = false;
        console.warn("串口关闭失败，串口已是关闭状态！");
        return false;
    }
}





//     <OBJECT id=MSComm1 CLASSID="clsid:648A5600-2C6E-101B-82B6-000000000014"
// codebase="MSCOMM32.OCX" type="application/x-oleobject">
//     <!--<PARAM   NAME="CommPort"   VALUE="2"/>-->
//     <!--<PARAM   NAME="DataBits"   VALUE="8"/>-->
//     <!--<PARAM   NAME="StopBits"   VALUE="1"/>-->
//     <!--<PARAM   NAME="BaudRate"   VALUE="9600"/>-->
//     <!--<PARAM   NAME="Settings"   VALUE="9600,N,8,1"/>-->
//
//     <PARAM   NAME="RTSEnable"   VALUE="1"/>
//     <PARAM   NAME="DTREnable"   VALUE="1"/>
//     <PARAM   NAME="Handshaking"   VALUE="0"/>
//     <PARAM   NAME="NullDiscard"   VALUE="0"/>
//     <PARAM   NAME="ParityReplace"   VALUE="?"/>
//
//     <PARAM   NAME="EOFEnable"   VALUE="0"/>
//     <PARAM   NAME="InputMode"   VALUE="0"/>
//     <PARAM   NAME="InBufferSize"   VALUE="1024"/>
//     <PARAM   NAME="InputLen"   VALUE="0"/>
//     <PARAM   NAME="OutBufferSize"   VALUE="512"/>    //发送缓冲区大小
//
//     <PARAM   NAME="SThreshold"   VALUE="0"/> //发送缓冲区触发事件门限
//     <PARAM   NAME="RThreshold"   VALUE="1"/> //接收缓冲区触发事件门限
//
//     </OBJECT>

// 1).CommPort：设置或返回串行端口号，缺省为1。
// 2).Setting：设置或返回串口通信参数，格式为“波特率，奇偶校验位，数据位，停止位”。例如：MSComm1.Setting:=9600,n,8,1
// 3).PortOpen：打开或关闭串行端口，格式为：MSComm1.PortOpen:={True|False}
// 4).InBufferSize：设置或返回接收缓冲区的大小，缺省值为1024字节。
// 5).InBufferCount：返回接收缓冲区内等待读取的字节数，可通过设置该属性为0来清空接收缓冲区。
// 6).RThreshold：该属性为一阈值，它确定当接收缓冲区内的字节个数达到或超过该值后就产生代码为ComEvReceive的OnComm事件。
// 7).SThreshold：该属性为一阈值，它确定当发送缓冲区内的字节个数少于该值后就产生代码为ComEvSend的OnComm事件。
// 8).InputLen：设置或返回接收缓冲区内用Input读入的字节数，设置该属性为0表示Input读取整个缓冲区的内容。
// 9).Input：从接收缓冲区读取一串字符。
// 10).OutBufferSize：设置或返回发送缓冲区的大小，缺省值为512字节。
// 11).OutBufferCount：返回发送缓冲区内等待发送的字节数，可通过设置该属性为0来清空缓冲区。　　
// 12).OutPut：向发送缓冲区传送一串字符。
// 在通信过程中发生的错误或事件会引发OnComm事件，并由CommEvent属性值反映错误类型，程序根据该属性值来执行不同的操作。CommEvent属性值及其含义如下：
// 1).ComEvSend：值为1，发送缓冲区的内容少于SThreshold指定的值。
// 2).ComEvReceive：值为2，接收缓冲区内字符数达到RThreshold指定的值。
// 3).ComEvFrame：值为1004，硬件检测到帧错误。
// 4).ComEvRxOver：值为1008，接收缓冲区溢出。
// 5).ComEvTxFull：值为1010，发送缓冲区溢出。
// 6).ComEvRxParity：值为1009，奇偶校验错误。
// 7).ComEvEOF：值为7，接收数据中出现文件尾（ASCII码为26）字符。